package com.xiang.publicdemo.module1.repository.impl;

import org.springframework.beans.BeanWrapper;
import org.springframework.beans.NotReadablePropertyException;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.util.ReflectionUtils;

import javax.persistence.Column;
import java.lang.reflect.Field;
import java.sql.Types;
import java.util.Map;
import java.util.Set;

/**
 * 通过反射，获取bean 属性和值
 */
public class MyBeanPropertySqlParameterSource extends BeanPropertySqlParameterSource {
    private final BeanWrapper beanWrapper;
    private Object source;

    public MyBeanPropertySqlParameterSource(Object object, Map<String, Class<?>> fieldsType) {
        super(object);
        this.source = object;
        this.beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(object);
        Set<String> keySet = fieldsType.keySet();
        for (String fieldName : keySet) {
            this.registerSqlType(fieldName, Types.VARCHAR);
        }
    }

    @Override
    public Object getValue(String paramName) throws IllegalArgumentException {
        Object result = null;
        try {
            if (source != null) {
                Field field = ReflectionUtils.findField(source.getClass(), paramName);
                Column column = field.getAnnotation(Column.class);
                if (column != null) {
                    field.setAccessible(true);
                    // 此处获取的是Student的teacher属性
                    Object object = field.get(source);
                    if (object != null) {
                        String name = column.name();
                        Field findField = ReflectionUtils.findField(object.getClass(), name);
                        findField.setAccessible(true);
                        // 此处获取的是teacher上面的@column标注的某个字段的属性，比如gco。
                        result = findField.get(object);
                        //findField.setAccessible(false);
                    }
                    //field.setAccessible(false);
                } else {
                    result = this.beanWrapper.getPropertyValue(paramName);
                }
            } else {
                result = this.beanWrapper.getPropertyValue(paramName);
            }
        } catch (NotReadablePropertyException | IllegalAccessException ex) {
            throw new IllegalArgumentException(ex.getMessage());
        }
        return result;
    }
}
